﻿#region License statement
// NJamb, a specification and delta-specification DSL
// Copyright (c) 2010-2011, Mark Knell
// Published under the MIT License; all other rights reserved
#endregion

#region using...
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using NJamb.Parser.SpecificationBuilders.SubjectHas.Delta.Enumerable;
using NJamb.Parser.SpecificationBuilders.SubjectIs.Delta.Enumerable;
using NJamb.Specifications.Delta;
using NJamb.Specifications.Simple;
using Stile.Patterns.SelfDescribingPredicates;
using Stile.Patterns.SelfDescribingPredicates.Evaluators;
#endregion

namespace NJamb.Parser.SpecificationBuilders.Delta.Enumerable
{
    public class EnumerableDeltaSpecificationBuilder<TSubject, TItem> : DeltaSpecificationBuilder<TSubject>,
        IEnumerableDeltaSpecificationBuilder<TSubject, TItem>,
        ICollaboratingSpecificationBuilder<TSubject, IDeltaSpecification>
        where TSubject : class, IEnumerable<TItem>
    {
        public EnumerableDeltaSpecificationBuilder(ICollaboratingSimpleSpecification<TSubject> before)
            : base(before)
        {
            LazyIs =
                new Lazy<INegatableEnumerableDeltaIs<TSubject, TItem>>(
                    () => new NegatableEnumerableDeltaIs<TSubject, TItem>(this, Negated.False));
            LazyHas = new Lazy<IEnumerableDeltaHas<TSubject, TItem>>(() => new EnumerableDeltaHas<TSubject, TItem>(this));
        }

        public IEnumerableDeltaHas<TSubject, TItem> Has
        {
            get { return LazyHas.Value; }
        }
        public INegatableEnumerableDeltaIs<TSubject, TItem> Is
        {
            get { return LazyIs.Value; }
        }
        public Lazy<IEnumerableDeltaHas<TSubject, TItem>> LazyHas { get; private set; }
        public Lazy<INegatableEnumerableDeltaIs<TSubject, TItem>> LazyIs { get; private set; }
        public ICollaboratingSpecificationBuilder<TSubject, IDeltaSpecification> Xray
        {
            get { return this; }
        }

        public IDeltaSpecification Satisfies(ISelfDescribingPredicate<TSubject> selfDescribingPredicate)
        {
            return Specify(selfDescribingPredicate);
        }

        public IDeltaSpecification Satisfies(Expression<Func<TSubject, bool>> lambdaPredicate)
        {
            Evaluator<TSubject, TSubject> evaluator = Expect<TSubject>.Satisfies(lambdaPredicate);
            return Satisfies(evaluator);
        }
    }
}
